﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PS3Helpers.Helpers;

namespace PS3Helpers
{
    public class VirtualDirectory
    {
        private PS3PackageFile _owner;
        internal VirtualDirectory _parent = null;
        private string _name;
        private VirtualDirectoryCollection _directories;
        private VirtualFileCollection _files;

        internal VirtualDirectory(PS3PackageFile owner)
        {
            _owner = owner;
            _name = "Root";
        }

        public VirtualDirectory(string name)
        {
            if (string.IsNullOrEmpty(name))
                throw new Exception("Name can't be an empty string!");

            _name = name;
        }

        // Clone the VirtualDirectory object
        public VirtualDirectory(VirtualDirectory source)
        {
            _name = source._name;

            foreach (VirtualDirectory subdir in source.Directories)
            {
                VirtualDirectory newdir = new VirtualDirectory(subdir);
                Directories.Add(newdir);
            }

            foreach (VirtualFile subfile in source.Files)
            {
                VirtualFile newfile = new VirtualFile(subfile);
                Files.Add(newfile);
            }
        }

        internal VirtualDirectory Parent
        {
            get { return _parent; }
        }

        public VirtualDirectoryCollection Directories
        {
            get
            {
                if (_directories == null)
                {
                    _directories = new VirtualDirectoryCollection(this);
                }

                return _directories;
            }
        }

        public VirtualFileCollection Files
        {
            get
            {
                if (_files == null)
                {
                    _files = new VirtualFileCollection(this);
                }

                return _files;
            }
        }

        public string Name
        {
            get { return _name; }
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new Exception("Invalid folder name");

                _name = value;
            }
        }

        public VirtualDirectory AddDirectory(string name)
        {
            VirtualDirectory result = new VirtualDirectory(name);
            Directories.Add(result);

            return result;
        }

        public VirtualFile AddLockedFile(string name)
        {
            VirtualFile result = new VirtualFile(name, true, "", "");
            Files.Add(result);

            return result;
        }

        internal PS3PackageFile GetPackageFile()
        {
            if (_parent != null)
                return _parent.GetPackageFile();

            return _owner;
        }
    }

    public class VirtualDirectoryCollection : ListWithChangedEvent<VirtualDirectory>
    {
        private VirtualDirectory _owner = null;

        internal VirtualDirectoryCollection(VirtualDirectory owner)
        {
            _owner = owner;
        }

        public VirtualDirectoryCollection()
        {
        }

        protected override void OnChanged(ListWithChangedEventType changetype, VirtualDirectory element)
        {
            base.OnChanged(changetype, element);

            switch (changetype)
            {
                case ListWithChangedEventType.Add:
                case ListWithChangedEventType.Insert:
                    {
                        lock (element)
                        {
                            if ((element._parent != null) && (element._parent != _owner))
                            {
                                base.Remove(element);
                                throw new Exception("Item already exists in another collection!");
                            }

                            element._parent = _owner;
                        }
                        break;
                    }
                case ListWithChangedEventType.Remove:
                    {
                        lock (element)
                        {
                            if (element._parent == _owner)
                            {
                                element._parent = null;
                            }
                        }

                        break;
                    }
            }
        }
    }
}
